package controller

import (
	"github.com/labstack/echo"
	"net/http"

	"fmt"
	"m-project-admin/app/entity"
	"m-project-admin/app/manager"
	"m-project-admin/app/model"
	"m-project-admin/app/utils"
	"strings"
	"time"
)

// SsoLogin
// http://127.0.0.1:14001/ssoLogin?key=0b5d7ed54bee16756a7579c6718ab01e3d1b75eb&auth_back_url=xxx
func SsoLogin(c echo.Context) error {
	key := c.QueryParam("key")
	authBackUrl := c.QueryParam("auth_back_url")

	if key == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "key is empty"})
	}
	if authBackUrl == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "auth_back_url is empty"})
	}

	// 判断APP是否存在
	app, _, _ := manager.GetAppByKey(key)
	if app.Id.Hex() == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "key is error"})
	}

	// 渲染结果到模板
	data := make(map[string]interface{})
	data["key"] = key
	data["auth_back_url"] = authBackUrl
	return c.Render(http.StatusOK, "sso_login.html", data)
}

// ssoDoLogin
func SsoDoLogin(c echo.Context) error {
	key := c.FormValue("key")
	authBackUrl := c.FormValue("auth_back_url")
	account := c.FormValue("account")
	password := c.FormValue("password")

	if key == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "数据错误"})
	}
	if authBackUrl == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "数据错误"})
	}
	if account == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "账号不能为空"})
	}
	if password == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "密码不能为空"})
	}

	app, _, _ := manager.GetAppByKey(key)

	if app.Id.Hex() == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "key is error"})
	}

	// 回调地址
	callbackUrl := app.Callback_url

	// 检查登录
	accountObj, isLogin, msg := manager.SsoCheckLogin(app.Id.Hex(), account, password)

	if !isLogin {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: msg})
	}

	accountId := accountObj.Id.Hex()

	// 查询是否存在token
	token, err := manager.GetTokenByAccountId(accountId)
	if err != nil {
		// 生成token
		uniqStr := fmt.Sprintf("%s_%d", accountId, int(time.Now().Unix()))
		token = utils.Sha1s([]byte(uniqStr))

		// 存储登录状态 3天
		err = manager.SetTokenAccount(token, accountId, time.Second*3*24*3600)
		if err != nil {
			return c.JSON(http.StatusOK, entity.Response{En: 402, Em: err.Error()})
		}
	}

	// 重定向到回调App接口
	data := make(map[string]interface{})
	data["redirect_url"] = callbackUrl + "?token=" + token + "&auth_back_url=" + authBackUrl
	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "登录成功", Data: data})
}

// SsoLogout
// http://127.0.0.1:14001/ssoLogout?key=0b5d7ed54bee16756a7579c6718ab01e3d1b75eb&token=xxx
func SsoLogout(c echo.Context) error {
	key := c.QueryParam("key")
	token := c.QueryParam("token")

	if key == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "key is empty"})
	}
	if token == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "token is empty"})
	}

	app, _, _ := manager.GetAppByKey(key)

	if app.Id.Hex() == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "key is error"})
	}

	callbackUrl := app.Callback_url

	// 删除token
	manager.DelTokenAccountByToken(token)

	// 重定向到回调App接口
	return c.Redirect(http.StatusFound, callbackUrl)
}

// SsoCheck
// http://127.0.0.1:14001/ssoCheck
// key  secret  token
func SsoCheck(c echo.Context) error {
	key := c.FormValue("key")
	secret := c.FormValue("secret")
	token := c.FormValue("token")

	if key == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "key is empty"})
	}
	if secret == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "secret is empty"})
	}
	if token == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "token is empty"})
	}

	app, _, _ := manager.GetAppByKey(key)
	if app.Id.Hex() == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "key is error"})
	}

	if app.App_secret != secret {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "secret is error"})
	}

	// 检查token是否有效
	accountId, err := manager.GetAccountIdByToken(token)
	if err != nil {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "check is error"})
	}

	// 查accountInfo
	account, err := manager.GetAccountById(accountId)
	if err != nil {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "check search account is fail"})
	}

	// 返回结果
	data := make(map[string]interface{})
	data["token"] = token
	data["accountId"] = accountId
	data["name"] = account.Name
	data["account"] = account.Account
	data["photo"] = manager.FormatAccountPhoto(account.Photo)
	data["is_super"] = account.Is_Super
	data["department"] = account.Department
	data["department_desc"] = manager.DepartmentDesc[account.Department]
	data["business_lines"] = account.BusinessLines
	data["all_business_lines"] = model.BusinessList
	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功", Data: data})
}

// SsoAccountProfile
// http://127.0.0.1:14001/ssoAccountProfile
// accountId key  secret  token
func SsoAccountProfile(c echo.Context) error {
	accountId := c.FormValue("accountId")
	key := c.FormValue("key")
	secret := c.FormValue("secret")
	token := c.FormValue("token")

	if accountId == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "accountId is empty"})
	}
	if key == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "key is empty"})
	}
	if secret == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "secret is empty"})
	}
	if token == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "token is empty"})
	}

	app, _, _ := manager.GetAppByKey(key)
	if app.Id.Hex() == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "key is error"})
	}

	if app.App_secret != secret {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "secret is error"})
	}

	// 检查token是否有效
	cacheAccountId, err := manager.GetAccountIdByToken(token)
	if err != nil || cacheAccountId == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "check is error"})
	}

	// 查询account信息
	accountObj, err := manager.GetAccountById(accountId)
	if accountObj.Id.Hex() == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "account is error"})
	}

	// 返回结果
	data := make(map[string]interface{})
	data["accountId"] = accountId
	data["name"] = accountObj.Name
	data["account"] = accountObj.Account
	data["photo"] = manager.FormatAccountPhoto(accountObj.Photo)
	data["is_super"] = accountObj.Is_Super
	data["department"] = accountObj.Department
	data["department_desc"] = manager.DepartmentDesc[accountObj.Department]
	data["business_lines"] = accountObj.BusinessLines
	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功", Data: data})
}

// SsoAccountProfiles
// http://127.0.0.1:14001/ssoAccountProfiles
// accountIds key  secret  token
func SsoAccountProfiles(c echo.Context) error {
	accountIds := c.FormValue("accountIds")
	key := c.FormValue("key")
	secret := c.FormValue("secret")
	token := c.FormValue("token")

	if accountIds == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "accountId is empty"})
	}
	accountIdsArray := strings.Split(accountIds, ",")
	if key == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "key is empty"})
	}
	if secret == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "secret is empty"})
	}
	if token == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "token is empty"})
	}

	app, _, _ := manager.GetAppByKey(key)
	if app.Id.Hex() == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "key is error"})
	}

	if app.App_secret != secret {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "secret is error"})
	}

	// 检查token是否有效
	cacheAccountId, err := manager.GetAccountIdByToken(token)
	if err != nil || cacheAccountId == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "check is error"})
	}

	accounts := make(map[string]map[string]interface{})
	for _, accountId := range accountIdsArray {
		// 查询account信息
		accountObj, err := manager.GetAccountById(accountId)
		if err != nil || accountObj.Id.Hex() == "" {
			continue
		}

		item := make(map[string]interface{})
		item["accountId"] = accountId
		item["name"] = accountObj.Name
		item["account"] = accountObj.Account
		item["photo"] = manager.FormatAccountPhoto(accountObj.Photo)
		item["is_super"] = accountObj.Is_Super
		item["department"] = accountObj.Department
		item["department_desc"] = manager.DepartmentDesc[accountObj.Department]
		item["business_lines"] = accountObj.BusinessLines
		accounts[accountId] = item
	}

	// 返回结果
	data := make(map[string]interface{})
	data["accounts"] = accounts
	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功", Data: data})
}

// SsoSearchAdmin
// http://127.0.0.1:14001/ssoSearchAdmin
// name key  secret  token
func SsoSearchAdmin(c echo.Context) error {
	name := c.FormValue("name")
	key := c.FormValue("key")
	secret := c.FormValue("secret")
	token := c.FormValue("token")

	if name == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "name is empty"})
	}
	if key == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "key is empty"})
	}
	if secret == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "secret is empty"})
	}
	if token == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "token is empty"})
	}

	app, _, _ := manager.GetAppByKey(key)
	if app.Id.Hex() == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "key is error"})
	}

	if app.App_secret != secret {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "secret is error"})
	}

	// 检查token是否有效
	cacheAccountId, err := manager.GetAccountIdByToken(token)
	if err != nil || cacheAccountId == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "check is error"})
	}

	// 查询account信息
	accountObj, err := manager.GetAccountByName(name)
	if accountObj.Id.Hex() == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "account is error"})
	}

	// 返回结果
	data := make(map[string]interface{})
	data["accountId"] = accountObj.Id.Hex()
	data["name"] = accountObj.Name
	data["account"] = accountObj.Account
	data["photo"] = manager.FormatAccountPhoto(accountObj.Photo)
	data["is_super"] = accountObj.Is_Super
	data["department"] = accountObj.Department
	data["department_desc"] = manager.DepartmentDesc[accountObj.Department]
	data["business_lines"] = accountObj.BusinessLines
	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功", Data: data})
}

// SsoAccountList
// http://127.0.0.1:14001/ssoAccountList
// key  secret  token
func SsoAccountList(c echo.Context) error {
	key := c.FormValue("key")
	secret := c.FormValue("secret")
	token := c.FormValue("token")

	if key == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "key is empty"})
	}
	if secret == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "secret is empty"})
	}
	if token == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "token is empty"})
	}

	app, _, _ := manager.GetAppByKey(key)
	if app.Id.Hex() == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "key is error"})
	}

	if app.App_secret != secret {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "secret is error"})
	}

	// 检查token是否有效
	cacheAccountId, err := manager.GetAccountIdByToken(token)
	if err != nil || cacheAccountId == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "check is error"})
	}

	// 查询account信息
	accountObjs, err := manager.GetAllAccounts()
	if err != nil {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "search is error"})
	}

	accounts := make(map[string]map[string]interface{})
	for _, accountObj := range accountObjs {
		accountId := accountObj.Id.Hex()
		item := make(map[string]interface{})
		item["accountId"] = accountId
		item["name"] = accountObj.Name
		item["account"] = accountObj.Account
		item["photo"] = manager.FormatAccountPhoto(accountObj.Photo)
		item["is_super"] = accountObj.Is_Super
		item["department"] = accountObj.Department
		item["department_desc"] = manager.DepartmentDesc[accountObj.Department]
		item["business_lines"] = accountObj.BusinessLines
		accounts[accountId] = item
	}

	// 返回结果
	data := make(map[string]interface{})
	data["accounts"] = accounts
	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功", Data: data})
}

// SsoSearchAccountPremissions
// http://127.0.0.1:14001/ssoSearchAccountPremissions
// accountId key  secret  token
func SsoSearchAccountPremissions(c echo.Context) error {
	accountId := c.FormValue("accountId")
	key := c.FormValue("key")
	secret := c.FormValue("secret")
	token := c.FormValue("token")

	if accountId == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "accountId is empty"})
	}
	if key == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "key is empty"})
	}
	if secret == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "secret is empty"})
	}
	if token == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "token is empty"})
	}

	app, _, _ := manager.GetAppByKey(key)
	if app.Id.Hex() == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "key is error"})
	}

	if app.App_secret != secret {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "secret is error"})
	}

	// 检查token是否有效
	cacheAccountId, err := manager.GetAccountIdByToken(token)
	if err != nil || cacheAccountId == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "check is error"})
	}

	// 查询account信息
	accountObj, err := manager.GetAccountById(accountId)
	if accountObj.Id.Hex() == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: "account is error"})
	}

	// 该用户的角色
	roleIds := accountObj.Roles

	// 查询角色信息
	roles, err := manager.GetAllRolesByIds(roleIds)
	if err != nil {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: err.Error()})
	}

	accountPremissions := make([]string, 0)
	for _, roleObj := range roles {
		premissions := roleObj.Premissions
		accountPremissions = append(accountPremissions, premissions...)
	}

	if len(accountPremissions) == 0 {
		data := make(map[string]interface{})
		data["premissions"] = nil
		return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功", Data: data})
	}

	// 查询权限信息
	rows, err := manager.GetAllPremissionsByIds(accountPremissions)
	if err != nil {
		return c.JSON(http.StatusOK, entity.Response{En: 401, Em: err.Error()})
	}

	premissions := make(map[string]map[string]interface{})
	for _, premissionObj := range rows {
		key := premissionObj.Key
		item := make(map[string]interface{})
		item["key"] = key
		item["name"] = premissionObj.Name
		premissions[key] = item
	}

	// 返回结果
	data := make(map[string]interface{})
	data["premissions"] = premissions
	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功", Data: data})
}
